#include <iostream>        
#include <thread>             
#include <mutex>              
#include <condition_variable> 
#include <string>

class Exception {
public:
    Exception(const std::string& errmsg, int id)
        : _errmsg(errmsg),
          _id(id)
    {}

    virtual std::string what() const {
        return _errmsg;
    }
protected:
    std::string _errmsg;
    int _id;
};

class SqlException : public Exception
{
public:
    SqlException(const std::string &errmsg, int id, const std::string &sql)
        : Exception(errmsg, id), 
          _sql(sql)
    {}

    virtual std::string what() const
    {
        std::string str = "SqlException:";
        str += _errmsg;
        str += "->";
        str += _sql;
        return str;
    }
private:
    const std::string _sql;
};

class CacheException : public Exception {
public:
    CacheException(const std::string& errmsg, int id)
        : Exception(errmsg, id)
    {}

    virtual std::string what() const {
        std::string str("CacheException:");
        str += _errmsg;
        return str;
    }
};

class HttpServerException : public Exception {
public:
    HttpServerException(const std::string& errmsg, int id, const std::string type)
        : Exception(errmsg, id),
          _type(type)
    {}

    virtual std::string what() const {
        std::string str("HttpServerException:");
        str += _type;
        str += ":";
        str += _errmsg;
        return str;
    }
private:
    const std::string _type;
};

void SQLMgr()
{
    srand(time(0));
    if (rand() % 7 == 0)
        throw SqlException("权限不足", 100, "select * from name = '张三'");
    else
        std::cout << "Sql执行成功" << std::endl;
}

void CacheMgr()
{
    srand(time(0));
    if (rand() % 5 == 0)
        throw CacheException("权限不足", 100);
    else if (rand() % 6 == 0)
        throw CacheException("数据不存在", 101);
    else
        std::cout << "Cache无异常" << std::endl;
    
    SQLMgr();
}

void HttpServer()
{
    // ...
    srand(time(0));
    if (rand() % 3 == 0)
        throw HttpServerException("请求资源不存在", 100, "get");
    else if (rand() % 4 == 0)
        throw HttpServerException("权限不足", 101, "post");
    else
        std::cout << "HttpServer无异常" << std::endl;
    CacheMgr();
}

// int main() {
//     while (true) {
//         std::this_thread::sleep_for(std::chrono::seconds(1));
//         try {
//             HttpServer();
//         } catch (const Exception& e) {
//             // 捕获基类对象
//             std::cout << e.what() << std::endl;
//         } catch (...) {
//             std::cout << "Unkown Exception" << std::endl;
//         }
//     }
//     return 0;
// }

void SendMsg(const std::string& msg) {}

// int main() {
//     int n = 10;
//     while (true) {
//         try {
//         SendMsg("在吗？");            
//         } catch (const Exception& e) {
//             // 当getid获取为3的时候说明为网络错误
//             if (e.getid() == 3) {
//                 --n;
//                 if (n == 0)
//                     throw;
//                 else
//                     continue;
//             } else {
//                 throw;
//             }
//         } 
//     }
//     return 0;
// }

// // 这里表示这个函数会抛出A/B/C/D中的某种类型的异常
// void fun() throw(A, B, C, D);
// // 这里表示这个函数只会抛出bad_alloc的异常
// void* operator new (std::size_t size) throw (std::bad_alloc);
// // 这里表示这个函数不会抛出异常
// void* operator delete (std::size_t size, void* ptr) throw();
// // C++11 中新增的noexcept，表示不会抛异常
// thread() noexcept;
// thread (thread&& x) noexcept;


double Division(int a, int b)
{
    // b == 0时抛出异常
    if (b == 0) 
        throw "Division by zero condition!";
    
    return (double)a / (double)b;
}

// void Func()
// {
//     int *array1 = new int[10];
//     try {
//         int *array2 = new int[10];
//         try {
//             int len, time;
//             std::cin >> len >> time;
//             std::cout << Division(len, time) << std::endl;
//         } catch (...) {
//             std::cout << "delete []" << array2 << std::endl;
//             delete[] array2;
//             // 捕获什么抛出什么
//             throw;
//         }
//         // ... other code
//         delete[] array2;
//     } catch (...) {
//         std::cout << "delete []" << array1 << std::endl;
//         delete[] array1;
//         throw;
//     }
//     // ... other code
//     delete[] array1;
// }

template <typename T>
class SmartPtr {
public:
    SmartPtr(T* ptr)
        : _ptr(ptr)
    {}

    T& operator*() {
        return *_ptr;
    }

    T* operator->() {
        return _ptr;
    }

    T& operator[](size_t i) {
        return _ptr[i];
    }

    T* get() {
        return _ptr;
    }

    ~SmartPtr() {
        delete[] _ptr;
    }
private:
    T* _ptr;
};

void Func() {
    SmartPtr<int> array1(new int[10]);
    SmartPtr<int> array2(new int[10]);
    int len, time;
    std::cin >> len >> time;
    std::cout << Division(len, time) << std::endl;
}

struct Date {
    int _year;
    int _month;
    int _day;
};

// int main() {
//     SmartPtr<int> sp(new int[10]);
//     SmartPtr<int> sp2(sp);
//     return 0;
// }

// #include <memory>

// int main() {
//     std::auto_ptr<int> sp1(new int);
//     std::auto_ptr<int> sp2(sp1);

//     *sp1 = 3;
//     return 0;
// }

int main() {
	std::shared_ptr<int> sp1((int*)malloc(sizeof(int)));
	std::shared_ptr<FILE> sp2(fopen("text.txt", "w"));

	return 0;
}